
// This version of TopicStates uses a singly-linked list to store
// topic objects.  This will use a little more memory than
// the VarStore version, but will be much more efficient
// with traversals (this.dump()).
function TopicStates()
{
	this.compress = false;
	this.isDirty = TopicStatesIsDirty;
	
	this.head = null;
	this.dirty = false;

	this.setTopic = TopicStatesSetTopic;
	this.resetTopic = TopicStatesResetTopic;
	this.getTopicState = TopicStatesGetTopic;
	this.dump = TopicStatesDump;
	this.load = TopicStatesLoad;
	this.clear = TopicStatesClear;
	this.clearRec = TopicStatesClearRec;
	
	return this;
}

function TopicStatesSetTopic(obj_topic)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objTopic = new Topic(obj_topic.section,obj_topic.topic,obj_topic.subtopic);

	if (this.head == null)
	{
		this.head = objTopic;
		this.head.next = null;
		this.dirty = true;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist do nothing and return immediately.
			if (objTopic.toString() == nextNode.toString())
			{
				return;
			}
			// If objTopic > nextNode, move to next node and repeat.
			if (objTopic.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				// We've reached the location in the list
				// where objTopic belongs, so go ahead
				// and splice it in.
				this.dirty = true;
				objTopic.next = nextNode;
				if (prevNode == nextNode) // if initially only one node.
				{
					this.head = objTopic;
				}
				else
				{
					prevNode.next = objTopic;
				}
				return;
			}
		}
		// We've reached the end.
		this.dirty = true;
		prevNode.next = objTopic;
		objTopic.next = null;
	}
}

function TopicStatesResetTopic(obj_topic)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objTopic = new Topic(obj_topic.section,obj_topic.topic,obj_topic.subtopic);
	
	// If list is empty, simply return.
	if (this.head == null)
	{
		return;
	}
	else if (this.head.toString() == objTopic.toString())
	{
		this.head = this.head.next;
		return;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist then remove it and return immediately.
			if (objTopic.toString() == nextNode.toString())
			{
				// The operation below will remove the reference
				// to nextNode, effectively deleting it from memory
				// through garbage collection.
				prevNode.next = nextNode.next;
				this.dirty = true;
				return;
			}
			// If objTopic > nextNode, move to next node and repeat.
			if (objTopic.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				return;
			}
		}
	}
}

function TopicStatesGetTopic(obj_topic)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objTopic = new Topic(obj_topic.section,obj_topic.topic,obj_topic.subtopic);
	
	// If list is empty, simply return false.
	if (this.head == null)
	{
		return false;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist then return true.
			if (objTopic.toString() == nextNode.toString())
			{
				return true;
			}
			// If objTopic > nextNode, move to next node and repeat.
			if (objTopic.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				return false;
			}
		}
	}
	return false;
}


function TopicStatesDump()
{
	var temp = "";
	var currSection, currTopic;
	currSection = currTopic = null;
	var counter = 1;

	var nextNode = this.head;
	while (nextNode != null)
	{
		if (nextNode.section == currSection && nextNode.topic == currTopic)
		{
			temp += "," + nextNode.subtopic;
		}
		else
		{
			currSection = nextNode.section;
			currTopic = nextNode.topic;
			temp += "S" + currSection + "T" + currTopic + "U" + nextNode.subtopic;
		}
		nextNode = nextNode.next;
	}
	this.dirty = false;
	if (this.compress)
	{
		return compressUnicodeString(temp);
	}
	else
	{
		return temp;
	}
}

function TopicStatesLoad(dataString)
{
	if (this.compress)
	{
		dataString = uncompressUnicodeString(dataString);
	}

	var beenThereArray = dataString.split("S");
	
	for (var i=1;i<beenThereArray.length;i++)
	{
		var index = null;
		var section, topic
		var subtopicArray = null;
		
		index = beenThereArray[i].indexOf("T");
		section = parseInt(beenThereArray[i].slice(0,index));
		beenThereArray[i] = beenThereArray[i].slice(index+1,beenThereArray[i].length);

		index = beenThereArray[i].indexOf("U");
		topic = parseInt(beenThereArray[i].slice(0,index));
		beenThereArray[i] = beenThereArray[i].slice(index+1,beenThereArray[i].length);
		
		subtopicArray = beenThereArray[i].split(",");
		for (var t=0;t<subtopicArray.length;t++)
		{
			this.setTopic(new Topic(section, topic, parseInt(subtopicArray[t])));
		}
	}
}

function TopicStatesClear()
{
	this.clearRec(this.head);
	this.head = null;
}

function TopicStatesClearRec(nodeRef)
{
	if (nodeRef != null)
	{
		this.clearRec(nodeRef.next);
		nodeRef.next = null;
	}
}

function TopicStatesIsDirty()
{
	return this.dirty;
}
